package com.sprucetec.live.interceptor;


import com.alibaba.dubbo.common.utils.StringUtils;
import com.alibaba.fastjson.JSONObject;
import com.sprucetec.live.util.CertificateAuthorityHttpClientUtil;
import com.sprucetec.live.util.HttpClientUtil;
import com.sprucetec.oas.response.NoPageResultModel;
import com.sprucetec.oas.response.RestResponseCode;
import lombok.extern.slf4j.Slf4j;
import org.apache.http.HttpEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.protocol.HTTP;
import org.apache.http.util.EntityUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;

import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.net.URLEncoder;
import java.nio.charset.Charset;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 特殊的登录拦截器
 * creater by lizhenbin 20191205
 * 目前用于需要拦截登录跳转页面的接口
 */
@Slf4j
public class SpecialInterceptor implements HandlerInterceptor {

    @Value("${sso.loginurl}")
    String ssoLoginurl;

    @Value("${auth.url}/user/tokeninfo")
    String ssoLoginCheckUrl;

    @Value(value = "${sso.user.cookie.name}")
    String userCookieName;

    @Value("${sso.loginurl}/?redirect_url=")
    String ssoRedirectUrlPC = "https://sso.test.yunshanmeicai.com/user/login/?redirect_url=";

    @Value("${sso.ding.loginurl}/?redirect_url=")
    String ssoRedirectUrlAPP = "http://sso.test.yuinshanmeicai.com/dingding/index/?redirect_url=";

    @Value("${oas.context.address}")
    String OAS_CONTEXT_ADDRESS_URL;

    @Override
    public void afterCompletion(HttpServletRequest httpRequest,
                                HttpServletResponse httpResponse, Object arg2, Exception arg3)
            throws Exception {
        //do nothing
    }

    @Override
    public void postHandle(HttpServletRequest httpRequest, HttpServletResponse httpResponse,
                           Object arg2, ModelAndView modelAndView) throws Exception {
        //do nothing
    }

    @Override
    public boolean preHandle(HttpServletRequest httpRequest, HttpServletResponse httpResponse,
                             Object arg2) throws Exception {
        try {
            String userToken = null;
            List<String> tokens = new ArrayList<>();
            log.warn("{LoginInterceptor:preHandle, queryString:{}}", httpRequest.getQueryString());
            Map<String, String> paramsMap = URLRequest(httpRequest.getQueryString());
            if (paramsMap.containsKey("user_token")) {
                if (StringUtils.isNotEmpty(paramsMap.get("user_token")) && !paramsMap.get("user_token").equals("null")) {
                    tokens.add(paramsMap.get("user_token"));
                }
            }
            Cookie[] cookies = httpRequest.getCookies();
            if (cookies != null) {
                //遍历cookie获取sso的token
                for (Cookie curCookie : cookies) {
                    if (userCookieName.equals(curCookie.getName())) {
                        tokens.add(curCookie.getValue());
                        break;
                    }
                }
            }
            // 判断是手机端还是PC端,如果是手机端，并判断是钉钉应用内部的，才进行免登的跳转
            String redirectUrl = "";
            String userAgent = httpRequest.getHeader("User-Agent");
            if (userAgent != null && !"".equals(userAgent) && HttpClientUtil.isMobileDevice(userAgent)) {
                redirectUrl = ssoRedirectUrlAPP + URLEncoder.encode(OAS_CONTEXT_ADDRESS_URL + httpRequest.getRequestURI() + "?" + httpRequest.getQueryString());
            } else {
                redirectUrl = ssoRedirectUrlPC + URLEncoder.encode(OAS_CONTEXT_ADDRESS_URL + httpRequest.getRequestURI() + "?" + httpRequest.getQueryString());
            }
            if (tokens.size() == 0) {//token为空，未登录
                httpResponse.sendRedirect(redirectUrl);
                return false;
            } else {
                //校验token
                String res = "";
                for (String str : tokens) {
                    res = checkUserToken(ssoLoginCheckUrl, str, httpRequest);
                    if (StringUtils.isNotEmpty(res)) {
                        userToken = str;
                        break;
                    }
                }
                String user = "";
                try {
                    JSONObject cas_info = JSONObject.parseObject(res).getJSONObject("data").getJSONObject("cas_info");
                    if (cas_info != null) {
                        user = cas_info.getString("usercode");
                    }
                } catch (Exception e) {
                    log.error(e.toString());
                }
                if (!StringUtils.isBlank(user)) {//有效
                    httpRequest.getSession().setAttribute("loginName", user);
                } else {//无效
                    httpResponse.sendRedirect(redirectUrl);
                    return false;
                }
            }
        } catch (Exception e) {
            log.error("Exception:{}", e);
            //发生异常,返回异常信息
            httpResponse.setContentType("application/json;charset=utf-8");
            httpResponse.getWriter().write(JSONObject.toJSONString(new NoPageResultModel(RestResponseCode.INTERNAL_ERROR, RestResponseCode.INTERNAL_ERROR_DESC, "")));
            return false;
        }
        return true;
    }

    /**
     * 校验token
     *
     * @param url   地址
     * @param token 用户token
     * @return 用户信息
     * @throws Exception 异常
     */
    private String checkUserToken(String url, String token, HttpServletRequest request) throws Exception {
        CloseableHttpClient httpClient = null;
        CloseableHttpResponse response = null;
        try {
            String realIp = HttpClientUtil.getRealIp(request);
            httpClient = new CertificateAuthorityHttpClientUtil();
            HttpPost httpPost = new HttpPost(url);
            httpPost.setHeader(HTTP.CONTENT_TYPE, "application/json;charset=UTF-8");
            httpPost.setHeader("text/html", "charset=UTF-8");
            StringEntity params = new StringEntity("{\"user_token\":\"" + token + "\",\"real_ip\":\"" + realIp + "\"}", "UTF-8");
            httpPost.setEntity(params);
            response = httpClient.execute(httpPost);
            // 获取响应对象
            HttpEntity resEntity = response.getEntity();
            if (resEntity != null) {
                String res = EntityUtils.toString(resEntity, Charset.forName("UTF-8"));
                if ("1".equals(JSONObject.parseObject(res).getString("ret")) && JSONObject.parseObject(res).getJSONObject("data") != null) {
//					return JSONObject.parseObject(res).getJSONObject("data").getJSONObject("cas_info").getString("usercode");
                    return res;
                } else {
                    log.warn("请求失败：{}", res);
                }
            } else {
                log.warn("请求系统列表,响应的数据为空");
            }
            // 销毁
            EntityUtils.consume(resEntity);
            return "";
        } catch (Exception e) {
            log.error("error:{}", e);
            return "";
        } finally {
            try {
                if (response != null) {
                    response.close();
                }
            } catch (IOException e) {
                log.error("queryAuthSystemsAndRoles: response.close() exception:{}", e);
            }
            try {
                if (httpClient != null) {
                    httpClient.close();
                }
            } catch (IOException e) {
                log.error("queryAuthSystemsAndRoles: httpClient.close() exception:{}", e);
            }
        }
    }

    /**
     * 解析出url参数中的键值对
     *
     * @param queryString
     * @return
     */
    private Map<String, String> URLRequest(String queryString) {
        Map<String, String> paramsMap = new HashMap<>();
        if (StringUtils.isEmpty(queryString)) {
            return paramsMap;
        }
        String varibaleKey = "";
        String[] arrSplit = queryString.split("[&]");
        for (String string : arrSplit) {
            if (string.indexOf("=") > -1) {
                varibaleKey = string.substring(0, string.indexOf("="));
                paramsMap.put(string.substring(0, string.indexOf("=")), string.substring(string.indexOf("=") + 1, string.length()));
            } else {
                // 处理&的问题
                String tempString = paramsMap.get(varibaleKey);
                paramsMap.put(varibaleKey, tempString + "&" + string);
            }
        }
        return paramsMap;
    }
}
